<?php
/**
 * weixin
 * @link      http://book.kfsimi.cn
 * @copyright Copyright (c) 2010-2018 张锋建.
 * @package   apiframe/tools
 * @author    张锋建  mail:1224103366@qq.com
 * @version   1.0 Beta
 * 说明：
 *      微信公众号模块！
 *      为了减少配置，重复调用！
 *      在下面常量中定义好微信的各个参数！
 *      配置完成后，可以直接调用各种函数！
 */
namespace apiframe\models; //使用命名空间

/*--------------------------------微信公众号常量设置---------------------------------*/

define('token' , 'zhangfengjian');//微信验证token，用于微信公众号初次验证时使用！
define('AppID' , 'wx81c74f9b7dffa061');//微信AppID，用于微信公众号初次验证时使用！
define('AppSecret' , 'd8c1e99c797ed7050cc6fb24346e851f');//微信AppSecret，用于微信公众号初次验证时使用！

/*--------------------------------------------------------------------------------*/



/*--------------------------------储存access_token数据库信息---------------------------------*/

     /*数据库是用来储存access_token信息，access_token微信官方过期时间为7200秒,每天2000次！
       数据库链接采用PHPgrace官方连接方式！使用前请确定已配置好数据库！
       必须有一个表包含以下字段信息：
                            【字段name，类型varchar】-自定义储存access_token字段的名称！
                            【字段access_token，类型varchar】-储存微信获取到的access_token令牌！
        标出字段必须包含     【字段time，类型varchar】-储存微信access_token的过期时间(时间戳)！
                            【字段count，类型int】-储存微信access_token的总调用次数！*/

    
define('database' , 'weixinapi');//要调用的数据库，请到框架config.php查看！
define('datasheet' , 'gongzhonghao_public');//储存access_token信息的数据表名
define('indexes' , '店面公众号');//储存微信access_tokende数据的索引名,必须保证唯一性！
define('deadline' , 6000);//微信access_tokende的过期时间，单位/秒！

/*-----------------------------------------------------------------------------------------*/


//类名与文件名一致
class weixin{

public function post ($url, $data,$geshi=null) {//post请求,可定义请求数据格式，默认json格式！直接返回服务端数据！

   if ($geshi == 'xml') {//请求或发生xml或文本格式数据
    	$geshi = 'Content-Type: text/xml;charset=utf-8';
    } elseif ($geshi == 'data') {//请求或发生data格式数据，主要用于文件上传
    	$geshi = 'Content-Type: multipart/form-data;charset=utf-8';
    } elseif ($geshi == 'json') {//请求或发生json格式数据
    	$geshi = 'Content-Type: application/json;charset=utf-8';
    } elseif ($geshi == 'form') {//请求或发生表单格式数据
    	$geshi = 'Content-Type: application/x-www-form-urlencoded';
    } else {  //如果是全都不是默认输出json格式
    	$geshi = 'Content-Type: application/json;charset=utf-8'; 	
    }  

    $ch = curl_init();  
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); //设置缓冲等待时间
    curl_setopt($ch, CURLOPT_HTTPHEADER, array ($geshi));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data); //传递一个作为HTTP “POST”操作的所有数据的字符串。 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
    // 线下环境不用开启curl证书验证, 未调通情况可尝试添加该代码
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);// 对认证证书来源的检查
    $data = curl_exec($ch);
    curl_close($ch);                
    return $data;  
} 

public function get ($url) {//get网络请求！直接返回服务端数据！
    // 初始化
    $curl = curl_init();
    // 设置url路径
    curl_setopt($curl, CURLOPT_URL, $url);
    // 将 curl_exec()获取的信息以文件流的形式返回，而不是直接输出。
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ;
    // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
    curl_setopt($curl, CURLOPT_BINARYTRANSFER, true) ;
    // CURLINFO_HEADER_OUT选项可以拿到请求头信息
    curl_setopt($curl, CURLINFO_HEADER_OUT, true);
    // 不验证SSL
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    // 执行
    $data = curl_exec($curl);
    // 打印请求头信息
    // echo curl_getinfo($curl, CURLINFO_HEADER_OUT);
    // 关闭连接
    curl_close($curl);
    // 返回数据
    return $data;
} 

public function Verificationtoken(){//微信公众号初次token验证,返回验证字段，请在调用端echo输出

      //echo model('weixin')->Verificationtoken();//快捷代码，粘贴可用！
     


    //获得参数 signature nonce token timestamp echostr
    $nonce     = $_GET['nonce'];
    $timestamp = $_GET['timestamp'];
    $echostr   = $_GET['echostr'];
    $signature = $_GET['signature'];
    //形成数组，然后按字典序排序
    $array = array();
    $array = array($nonce, $timestamp, token);
    sort($array);
    //拼接成字符串,sha1加密 ，然后与signature进行校验
    $str = sha1( implode( $array ) );
    if( $str == $signature && $echostr ){
        //第一次接入weixin api接口的时候
        return  $echostr;
    } 
}

public function getaccesstoken(){//数据库存取access_token令牌,过期自动更新！直接返回access_token字符串！
  

	 $this->db = db(datasheet,database);
     $this->db->query('select * from '.datasheet.' where name = ?',array(indexes));
     $data = $this->db->queryFetchAll();

		if (time() > $data[0]['time']) {

		    $res = $this->get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.AppID.'&secret='.AppSecret);
		    $access_token=json_decode($res,true);

		      $this->db = db(datasheet,database);
	        $data = array('access_token' =>$access_token['access_token'],'time' => time()+deadline);//按自定义时间过期
	        $dt = $this->db->where('name = ?', array(indexes))->update($data);

	        if ($dt) {
	         $this->db->where('name = ?', array(indexes))->field('count', 1);
	        }
			return $access_token['access_token'];
			// return $res; 
		} else {
	        return $data[0]['access_token'];
		}
}

public function getwxserver(){//获取微信服务器！直接返回json格式服务器列表字符串！
 $data = $this->get('https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token='.$this->getaccesstoken());
 return $data;	
}


public function getwxnews(){//获取微信公众号发来消息！直接解析返回数组格式！
	$xml = file_get_contents('php://input');//监听是否有数据传入
	if ($xml) {
		libxml_disable_entity_loader(true);//禁止加载外部实体，防止攻击！
	    $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);//XML转换为数组
		return $data;
	} else {
		return '没有收到微信消息';
	}	
}


public function wxsendtext(){//向微信公众号发送消息,两个参数1.消息类型！2.消息数组！直接解析返回数组格式！

}

public function responseMsg($data,$type=null) { //微信被动消息回复，第一个参数是数据数据，格式按照微信原装名称！第二个是消息类型！

    if ($type=='text') {
	  $textxml = "<xml>
      <ToUserName><![CDATA[%s]]></ToUserName>
      <FromUserName><![CDATA[%s]]></FromUserName>
      <CreateTime>%s</CreateTime>
      <MsgType><![CDATA[%s]]></MsgType>
      <Content><![CDATA[%s]]></Content>
      <FuncFlag>0</FuncFlag>
      </xml>"; 
      $resultStr = sprintf($textxml, $data['FromUserName'], $data['ToUserName'], time(), $type, $data['Content']);

    } else {
      $textxml = "<xml>
      <ToUserName><![CDATA[%s]]></ToUserName>
      <FromUserName><![CDATA[%s]]></FromUserName>
      <CreateTime>%s</CreateTime>
      <MsgType><![CDATA[%s]]></MsgType>
      <Content><![CDATA[%s]]></Content>
      <FuncFlag>0</FuncFlag>
      </xml>"; 
      $resultStr = sprintf($textxml, $data['FromUserName'], $data['ToUserName'], time(), $type, $data['Content']);

    }       
    echo $resultStr;
}
 









public function bug($sss=null){//调用调试模式，直接返回出错原因！

                /*********bug自检代码**********
                  $weixin=model('weixin');
                      $data=$weixin->bug();        
                      $this->__beiqia($data);*/

/****************************************************************************************************/
   $a = json_decode($this->get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.AppID.'&secret='.AppSecret));
   if (!key_exists("access_token",$a)) {
     
        return '没有获取到access_token，请检查AppID和AppSecret是否设置正确！';
   }
/****************************************************************************************************/
   if ($sss!==1) {
    $b = file_get_contents('php://input');//监听是否有数据传入
    if (!$b) {
      return '没有收到微信发来的消息，请检查微信URL服务器路径是否配置正确！(注意：如果用URL直接访问请在函数加参数1屏蔽此行)';
    }    
   }
/****************************************************************************************************/ 

    

 return '检查全部通过，如还有问题请检查您的使用方法是否正确！';

}





}